/* Tests for write_self.c
 *
 * Copyright 2008 Cian Synnott.
 * 
 * $Id: write_self_test.c 19 2009-11-27 20:46:48Z cian $
 */
#include <pwd.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <utmp.h>

#include "cutest/CuTest.h"
#include "write_self.h"

#define FAKEUTMP "testdata/fake_utmp"
#define FAKETTY "testdata/fake_tty"
#define MESSAGE "A test message\nEnjoy!"

/* Sets up a fake UTMP file with a single entry, pointing to a fake tty */
void setup_utmp(CuTest *tc) {
  FILE *utmp_file, *tty_file;
  struct utmp utmp_struct;
  struct passwd *pwd;

  pwd = getpwuid(getuid());
  if (pwd == NULL)
    CuFail(tc, "failed to read password structure for current uid");

  utmp_file = fopen(FAKEUTMP, "w");
  if (utmp_file == NULL)
    CuFail(tc, "failed to create fake utmp file");
  utmp_struct.ut_type = USER_PROCESS;
  strncpy(utmp_struct.ut_line, FAKETTY, UT_LINESIZE);
  strncpy(utmp_struct.ut_user, pwd->pw_name, UT_NAMESIZE);
  if (fwrite(&utmp_struct, sizeof(utmp_struct), 1, utmp_file) != 1)
    CuFail(tc, "failed to write fake utmp structure to fake utmp file");
  fclose(utmp_file);

  tty_file = fopen(FAKETTY, "w");
  if (tty_file == NULL)
    CuFail(tc, "failed to create fake tty file");
  fclose(tty_file);
  if (chmod(FAKETTY, S_IRUSR | S_IWUSR | S_IWGRP))
    CuFail(tc, "failed to chmod fake tty file rw--w----");

  utmpname(FAKEUTMP);
}

/* Cleans up fake UTMP file(s) */
void teardown_utmp(CuTest *tc) {
  if (unlink(FAKEUTMP))
    CuFail(tc, "failed to unlink fake utmp file");
  if (unlink(FAKETTY))
    CuFail(tc, "failed to unlink fake tty file");
}

#define BUFFER_SIZE 128

void TestWriteSelf(CuTest *tc) {
  FILE *reader;
  size_t num;
  char buffer[BUFFER_SIZE];

  set_device_prefix(".");
  setup_utmp(tc);

  if (write_self(MESSAGE))
    CuFail(tc, "failed to write message");

  reader = fopen(FAKETTY, "r");
  if (reader == NULL)
    CuFail(tc, "failed to reopen fake tty for reading");
  num = fread(&buffer, sizeof(char), BUFFER_SIZE, reader);
  buffer[num] = 0;
  fclose(reader);

  CuAssertStrEquals(tc, MESSAGE, buffer);

  teardown_utmp(tc);
}

int main(void) {
  CuString *output = CuStringNew();
  CuSuite* suite = CuSuiteNew();

  SUITE_ADD_TEST(suite, TestWriteSelf);

  CuSuiteRun(suite);
  CuSuiteSummary(suite, output);
  CuSuiteDetails(suite, output);
  printf("%s\n", output->buffer);

  return 0;
}
